package article

import (
	"context"
	"fmt"

	"BookStack/internal/domain/article"
	"BookStack/internal/domain/events"
)

// Service 文章应用服务接口
type Service interface {
	// ======文章基本操作======
	// 创建文章
	Create(ctx context.Context, req *CreateArticleRequest, authorID uint) (*ArticleResponse, error)
	// 通过ID获取文章
	GetByID(ctx context.Context, id uint) (*ArticleResponse, error)
	// 通过Slug获取文章
	GetBySlug(ctx context.Context, slug string) (*ArticleResponse, error)
	// 更新文章
	Update(ctx context.Context, req *UpdateArticleRequest, authorID uint) (*ArticleResponse, error)
	// 删除文章
	Delete(ctx context.Context, id uint) error

	// 文章列表查询
	List(ctx context.Context, page, pageSize int, filters map[string]interface{}) (*ArticleListResponse, error)
	// 通过作者获取文章列表
	ListByAuthor(ctx context.Context, authorID uint, page, pageSize int) (*ArticleListResponse, error)
	// 通过分类获取文章列表
	ListByCategory(ctx context.Context, categoryID uint, page, pageSize int) (*ArticleListResponse, error)
	// 获取推荐文章列表
	ListRecommended(ctx context.Context, page, pageSize int) (*ArticleListResponse, error)

	// ======文章状态管理======
	// 发布文章
	Publish(ctx context.Context, id uint) error
	// 归档文章
	Archive(ctx context.Context, id uint) error
	// 设置文章为草稿
	Draft(ctx context.Context, id uint) error
	// 设置文章状态
	SetStatus(ctx context.Context, req *SetStatusRequest) error
	// 设置文章推荐状态
	SetRecommend(ctx context.Context, req *SetRecommendRequest) error

	// ======文章统计相关======
	// 增加浏览量
	IncrementViews(ctx context.Context, id uint) error
	// 增加点赞数
	IncrementLikes(ctx context.Context, id uint) error
	// 减少点赞数
	DecrementLikes(ctx context.Context, id uint) error
}

// service 应用层文章服务实现
type service struct {
	articleService article.Service
	eventPublisher events.Publisher
}

// NewService 创建应用层文章服务
func NewService(articleService article.Service, eventPublisher events.Publisher) Service {
	return &service{
		articleService: articleService,
		eventPublisher: eventPublisher,
	}
}

// Create 创建文章
func (s *service) Create(ctx context.Context, req *CreateArticleRequest, authorID uint) (*ArticleResponse, error) {
	// 检查Slug是否已存在
	articleBySlug, err := s.articleService.GetBySlug(ctx, req.Slug)
	if err == nil && articleBySlug != nil {
		return nil, fmt.Errorf("slug已存在")
	}

	// 设置默认值
	content := req.Content
	if content == "" {
		content = "暂无内容"
	}

	// 调用领域服务创建文章（直接使用自定义slug）
	articleEntity, err := s.articleService.Create(
		ctx,
		req.Title,
		content,
		req.Summary,
		authorID,
		req.CategoryID,
		req.CoverImage,
		req.Slug, // 直接传入自定义slug
	)
	if err != nil {
		return nil, err
	}

	// 发布事件
	event := &events.ArticleCreatedEvent{
		ID:         articleEntity.ID,
		Title:      articleEntity.Title,
		AuthorID:   articleEntity.AuthorID,
		CategoryID: articleEntity.CategoryID,
		CreatedAt:  articleEntity.CreatedAt,
	}
	err = s.eventPublisher.Publish(ctx, events.NewEvent(events.ArticleCreatedEventType, event))
	if err != nil {
		// 记录错误但不影响主流程
		fmt.Printf("发布文章创建事件失败: %v\n", err)
	}

	// 转换为DTO并返回
	return FromEntity(articleEntity), nil
}

// GetByID 通过ID获取文章
func (s *service) GetByID(ctx context.Context, id uint) (*ArticleResponse, error) {
	// 调用领域服务获取文章
	articleEntity, err := s.articleService.GetByID(ctx, id)
	if err != nil {
		return nil, err
	}

	// 增加浏览量（异步）
	go func() {
		if err := s.articleService.IncrementViews(context.Background(), id); err != nil {
			// 异步操作失败，记录日志
			fmt.Printf("增加文章浏览量失败: %v\n", err)
		}
	}()

	// 转换为DTO并返回
	return FromEntity(articleEntity), nil
}

// GetBySlug 通过Slug获取文章
func (s *service) GetBySlug(ctx context.Context, slug string) (*ArticleResponse, error) {
	// 调用领域服务获取文章
	articleEntity, err := s.articleService.GetBySlug(ctx, slug)
	if err != nil {
		return nil, err
	}

	// 增加浏览量（异步）
	go func() {
		if err := s.articleService.IncrementViews(context.Background(), articleEntity.ID); err != nil {
			// 异步操作失败，记录日志
			fmt.Printf("增加文章浏览量失败: %v\n", err)
		}
	}()

	// 转换为DTO并返回
	return FromEntity(articleEntity), nil
}

// Update 更新文章
func (s *service) Update(ctx context.Context, req *UpdateArticleRequest, authorID uint) (*ArticleResponse, error) {
	// 获取文章以检查权限
	articleEntity, err := s.articleService.GetByID(ctx, req.ID)
	if err != nil {
		return nil, err
	}

	// 检查权限
	if articleEntity.AuthorID != authorID {
		return nil, fmt.Errorf("无权更新该文章")
	}

	// 设置自定义的slug
	articleEntity.Slug = req.Slug
	updatedArticle, err := s.articleService.Update(ctx, articleEntity.ID, articleEntity.Title, articleEntity.Content,
		articleEntity.Summary, articleEntity.CategoryID, articleEntity.CoverImage)
	if err != nil {
		return nil, err
	}

	// 使用更新后的文章实体
	articleEntity = updatedArticle

	// 发布事件
	event := &events.ArticleUpdatedEvent{
		ID:         articleEntity.ID,
		Title:      articleEntity.Title,
		AuthorID:   articleEntity.AuthorID,
		CategoryID: articleEntity.CategoryID,
		UpdatedAt:  articleEntity.UpdatedAt,
	}
	err = s.eventPublisher.Publish(ctx, events.NewEvent(events.ArticleUpdatedEventType, event))
	if err != nil {
		// 记录错误但不影响主流程
		fmt.Printf("发布文章更新事件失败: %v\n", err)
	}

	// 转换为DTO并返回
	return FromEntity(articleEntity), nil
}

// Delete 删除文章
func (s *service) Delete(ctx context.Context, id uint) error {
	// 获取文章信息用于事件
	articleEntity, err := s.articleService.GetByID(ctx, id)
	if err != nil {
		return err
	}

	// 调用领域服务删除文章
	if err := s.articleService.Delete(ctx, id); err != nil {
		return err
	}

	// 发布事件
	event := &events.ArticleDeletedEvent{
		ID:       id,
		Title:    articleEntity.Title,
		AuthorID: articleEntity.AuthorID,
	}
	err = s.eventPublisher.Publish(ctx, events.NewEvent(events.ArticleDeletedEventType, event))
	if err != nil {
		// 记录错误但不影响主流程
		fmt.Printf("发布文章删除事件失败: %v\n", err)
	}

	return nil
}

// List 获取文章列表
func (s *service) List(ctx context.Context, page, pageSize int, filters map[string]interface{}) (*ArticleListResponse, error) {
	// 调用领域服务获取文章列表
	articles, total, err := s.articleService.List(ctx, page, pageSize, filters)
	if err != nil {
		return nil, err
	}

	// 转换为DTO并返回
	return ToListResponse(articles, total), nil
}

// ListByAuthor 获取作者的文章列表
func (s *service) ListByAuthor(ctx context.Context, authorID uint, page, pageSize int) (*ArticleListResponse, error) {
	// 调用领域服务获取作者的文章列表
	articles, total, err := s.articleService.ListByAuthor(ctx, authorID, page, pageSize)
	if err != nil {
		return nil, err
	}

	// 转换为DTO并返回
	return ToListResponse(articles, total), nil
}

// ListByCategory 获取分类下的文章列表
func (s *service) ListByCategory(ctx context.Context, categoryID uint, page, pageSize int) (*ArticleListResponse, error) {
	// 调用领域服务获取分类下的文章列表
	articles, total, err := s.articleService.ListByCategory(ctx, categoryID, page, pageSize)
	if err != nil {
		return nil, err
	}

	// 转换为DTO并返回
	return ToListResponse(articles, total), nil
}

// ListRecommended 获取推荐文章列表
func (s *service) ListRecommended(ctx context.Context, page, pageSize int) (*ArticleListResponse, error) {
	// 调用领域服务获取推荐文章列表
	articles, total, err := s.articleService.ListRecommended(ctx, page, pageSize)
	if err != nil {
		return nil, err
	}

	// 转换为DTO并返回
	return ToListResponse(articles, total), nil
}

// Publish 发布文章
func (s *service) Publish(ctx context.Context, id uint) error {
	// 调用领域服务发布文章
	articleEntity, err := s.articleService.Publish(ctx, id)
	if err != nil {
		return err
	}

	// 发布事件
	event := &events.ArticlePublishedEvent{
		ID:          articleEntity.ID,
		Title:       articleEntity.Title,
		AuthorID:    articleEntity.AuthorID,
		CategoryID:  articleEntity.CategoryID,
		PublishedAt: articleEntity.UpdatedAt,
	}
	err = s.eventPublisher.Publish(ctx, events.NewEvent(events.ArticlePublishedEventType, event))
	if err != nil {
		// 记录错误但不影响主流程
		fmt.Printf("发布文章状态变更事件失败: %v\n", err)
	}

	return nil
}

// Archive 归档文章
func (s *service) Archive(ctx context.Context, id uint) error {
	// 调用领域服务归档文章
	articleEntity, err := s.articleService.Archive(ctx, id)
	if err != nil {
		return err
	}

	// 发布事件
	event := &events.ArticleArchivedEvent{
		ID:         articleEntity.ID,
		Title:      articleEntity.Title,
		AuthorID:   articleEntity.AuthorID,
		ArchivedAt: articleEntity.UpdatedAt,
	}
	err = s.eventPublisher.Publish(ctx, events.NewEvent(events.ArticleArchivedEventType, event))
	if err != nil {
		// 记录错误但不影响主流程
		fmt.Printf("发布文章归档事件失败: %v\n", err)
	}

	return nil
}

// Draft 设置文章为草稿
func (s *service) Draft(ctx context.Context, id uint) error {
	// 调用领域服务设置文章为草稿
	articleEntity, err := s.articleService.Draft(ctx, id)
	if err != nil {
		return err
	}

	// 发布事件
	event := &events.ArticleDraftedEvent{
		ID:        articleEntity.ID,
		Title:     articleEntity.Title,
		AuthorID:  articleEntity.AuthorID,
		DraftedAt: articleEntity.UpdatedAt,
	}
	err = s.eventPublisher.Publish(ctx, events.NewEvent(events.ArticleDraftedEventType, event))
	if err != nil {
		// 记录错误但不影响主流程
		fmt.Printf("发布文章草稿事件失败: %v\n", err)
	}

	return nil
}

// SetStatus 设置文章状态
func (s *service) SetStatus(ctx context.Context, req *SetStatusRequest) error {
	// 获取原始文章信息
	originalArticle, err := s.articleService.GetByID(ctx, req.ID)
	if err != nil {
		return err
	}

	previousStatus := originalArticle.Status

	// 调用领域服务设置文章状态
	articleEntity, err := s.articleService.SetStatus(ctx, req.ID, req.Status)
	if err != nil {
		return err
	}

	// 发布事件
	event := &events.ArticleStatusChangedEvent{
		ID:             articleEntity.ID,
		Title:          articleEntity.Title,
		AuthorID:       articleEntity.AuthorID,
		PreviousStatus: previousStatus,
		CurrentStatus:  articleEntity.Status,
		ChangedAt:      articleEntity.UpdatedAt,
	}
	err = s.eventPublisher.Publish(ctx, events.NewEvent(events.ArticleStatusChangedEventType, event))
	if err != nil {
		// 记录错误但不影响主流程
		fmt.Printf("发布文章状态变更事件失败: %v\n", err)
	}

	return nil
}

// SetRecommend 设置文章推荐状态
func (s *service) SetRecommend(ctx context.Context, req *SetRecommendRequest) error {
	// 获取原始文章信息
	originalArticle, err := s.articleService.GetByID(ctx, req.ID)
	if err != nil {
		return err
	}

	previousRecommend := originalArticle.IsRecommend

	// 调用领域服务设置文章推荐状态
	articleEntity, err := s.articleService.SetRecommend(ctx, req.ID, req.IsRecommend)
	if err != nil {
		return err
	}

	// 发布事件
	event := &events.ArticleRecommendChangedEvent{
		ID:                articleEntity.ID,
		Title:             articleEntity.Title,
		AuthorID:          articleEntity.AuthorID,
		PreviousRecommend: previousRecommend,
		CurrentRecommend:  articleEntity.IsRecommend,
		ChangedAt:         articleEntity.UpdatedAt,
	}
	err = s.eventPublisher.Publish(ctx, events.NewEvent(events.ArticleRecommendChangedEventType, event))
	if err != nil {
		// 记录错误但不影响主流程
		fmt.Printf("发布文章推荐状态变更事件失败: %v\n", err)
	}

	return nil
}

// IncrementViews 增加文章浏览量
func (s *service) IncrementViews(ctx context.Context, id uint) error {
	return s.articleService.IncrementViews(ctx, id)
}

// IncrementLikes 增加文章点赞数
func (s *service) IncrementLikes(ctx context.Context, id uint) error {
	return s.articleService.IncrementLikes(ctx, id)
}

// DecrementLikes 减少文章点赞数
func (s *service) DecrementLikes(ctx context.Context, id uint) error {
	return s.articleService.DecrementLikes(ctx, id)
}
